﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Odbc;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
using EzDesk.DesktopClient.ServiceLocator.CoreClientLoginService;
using EzDesk.DesktopClient.ServiceLocator.CoreClientService;
using EzDesk.Utility.Extensions;
using EzDesk.Utility.ServiceReference;
using EzDesk.DesktopClient.ServiceLocator.ClientTokenService;
using System.Net;
using EzDesk.Utility.Json;

namespace EzDesk.AutoCheckAttendance
{
    public class MainPresenter
    {
        private ICoreClientService CoreClientService
        {
            get { return ServiceReferenceFactory<ICoreClientService, CoreClientServiceClient>.GetService(); }
        }

        private ICoreClientLoginService CoreClientLoginService
        {
            get { return ServiceReferenceFactory<ICoreClientLoginService, CoreClientLoginServiceClient>.GetService(); }
        }

        private IClientTokenService ClientTokenService
        {
            get { return ServiceReferenceFactory<IClientTokenService, ClientTokenServiceClient>.GetService(); }
        }

        private object lockHelper = new object();

        private IMainView _view;

        private Timer _monitorFileSizeTimer;
        private DateTime _lastWriteTime = DateTime.MinValue;
        private readonly string _dbFileName = ConfigurationManager.AppSettings["dbFileName"];
        private DateTime _timeMark
        {
            get { return DateTime.Parse(ConfigurationManager.AppSettings["lastTimeMark"]); }
            set
            {
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                config.AppSettings.Settings["lastTimeMark"].Value = value.ToString();
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
        }
        private string _serviceHostName
        {
            get { return ConfigurationManager.AppSettings["serviceHostName"]; }
        }

        private void startTimer()
        {
            _monitorFileSizeTimer.Change(0, 2000);
        }

        private void stopTimer()
        {
            _monitorFileSizeTimer.Change(0, -1);
        }

        public void writeLog(string logStr)
        {
            string fullLogStr = "[" + DateTime.Now + "]:" + logStr;
            Debug.WriteLine(fullLogStr);
            _view.AddLog(fullLogStr);
        }

        // 委托类型的事件处理方法
        public event EventHandler OnFileSizeChanged;

        public MainPresenter(IMainView mainForm)
        {
            _view = mainForm;
            OnFileSizeChanged += MainPresenter_OnFileSizeChanged;

            initializeDatabaseFileSizeMonitors();
            _view.RefreshTimemark(_timeMark);
            _view.ChangeIsMonitorState(false);
        }

        void MainPresenter_OnFileSizeChanged(object sender, EventArgs e)
        {
            lock (lockHelper)
            {
                try
                {
                    stopTimer();
                    writeLog("FileSize Changed");

                    // 连接Access数据库
                    var connStr = @"Driver={Microsoft Access Driver (*.mdb)};pwd=couns113;Dbq=AccDBbk";
                    using (var conn = new OdbcConnection(connStr))
                    {
                        string timeStr = _timeMark.ToString("#yyyy-MM-dd HH:mm:ss#");
                        //导入请假类型
                        conn.Open();
                        string sqlStr = "SELECT tblEmp.EmpName, tblEvent.EventTime " +
                                        "FROM tblEvent " +
                                        "INNER JOIN tblEmp " +
                                        "ON tblEmp.CardId = tblEvent.CardId " +
                                        "WHERE tblEvent.EventTime > " + timeStr +
                                        "ORDER BY tblEvent.EventTime";
                        var cmd = new OdbcCommand(sqlStr, conn);
                        OdbcDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

                        var maxTime = _timeMark;
                        while (dr.Read())
                        {
                            var eventTime = (DateTime) (dr["EventTime"]);
                            var userName = (string) (dr["EmpName"]);
                            maxTime = eventTime > maxTime ? eventTime : maxTime;

                            addNewAttendanceInfo(userName, eventTime);
                            writeLog("尝试添加考勤记录 - 用户名： " + userName + "   时间： " + eventTime);
                        }
                        if (_timeMark != maxTime)
                        {
                            _timeMark = maxTime;

                            writeLog("时间戳更新到：" + _timeMark);
                            _view.RefreshTimemark(_timeMark);
                        }
                    }

                    startTimer();
                }

                catch (Exception ex)
                {
                    writeLog("未知错误： " + ex.Message);
                }
            }
        }

        private void addNewAttendanceInfo(string userName, DateTime eventTime)
        {
            writeLog("");
            writeLog("---");
            // 去掉userName前面的数字前缀
            var realName = getRealName(userName);
            if (string.IsNullOrEmpty(realName))
            {
                writeLog("名字出错： " + userName);
                return;
            }

            var users = CoreClientLoginService.GetUserNameForLogin(realName);
            if (users == null || users.Count() == 0)
            {
                writeLog("找不到名字： " + realName);
                return;
            }
            if (users.Count() > 1)
            {
                writeLog("找到重复的名字： " + realName);
            }

            var theUser = users.FirstOrDefault();

            var theUserId = theUser.Id;
            var actionEpochStr = eventTime.ToEpoch().ToString();

            // 如果没有登陆，那就登陆一下
            var loginUserProfile = CoreClientLoginService.Login("hxh", "123456");
            var tokenString = ClientTokenService.RequestToken(loginUserProfile.Id);

            // 发送一个http请求，完成登陆过程
            string autoCheckAttendanceUrl = string.Format(
                "http://" + _serviceHostName + "/attendance/doAutoCheckAttendance?userId={0}&time={1}&ez_auth_token={2}",
                theUserId, actionEpochStr, tokenString);

            var req = (HttpWebRequest) WebRequest.Create(autoCheckAttendanceUrl);
            req.MaximumAutomaticRedirections = 1000;
            req.CookieContainer = new CookieContainer();
            using (var response = (HttpWebResponse) req.GetResponse())
            {
                using (var reader = new StreamReader(response.GetResponseStream()))
                {
                    var jsonResult = reader.ReadToEnd();
                    var result = JsonHelper.JsonToDictionary(jsonResult);
                    if (result["State"] == "Success")
                    {
                        writeLog("搞定一个: " + theUser.Name + " 时间：" + eventTime + " " + result["Info"]);
                    }
                    else if (result["State"] == "Error")
                    {
                        writeLog("考勤记录无效，原因: " + result["Info"]);
                    }
                }
            }

            writeLog("---");
        }

        private string getRealName(string userName)
        {
            var prefixCount = 0;
            foreach (var ch in userName)
            {
                if (Char.IsDigit(ch)) prefixCount++;
                else break;
            }
            return userName.Substring(prefixCount);
        }

        private void initializeDatabaseFileSizeMonitors()
        {
            _monitorFileSizeTimer = new Timer(monitorFileSize, null, -1, -1);
        }

        private void monitorFileSize(object state)
        {   
            if (File.Exists(_dbFileName))
            {
                var fi = new FileInfo(_dbFileName);

                if (fi.LastWriteTime > _lastWriteTime)
                {
                    _lastWriteTime = fi.LastWriteTime;
                    FileSizeChanged();
                }
            }
        }

        private void FileSizeChanged()
        {
            if (OnFileSizeChanged != null)
            {
                OnFileSizeChanged(this, new EventArgs());
            }
        }

        public void StartMonitor()
        {
            lock (lockHelper)
            {
                _view.ChangeIsMonitorState(true);
                startTimer();
            }
        }

        public void StopMonitor()
        {
            lock (lockHelper)
            {
                _view.ChangeIsMonitorState(false);
                stopTimer();
            }
        }
    }
}
